import axios from 'axios';
import { Message } from '@arco-design/web-vue';
import { getToken } from '@/utils/auth';
import qs from 'query-string';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Protocol } from './types';
import type { PlacesSearchResult } from './map-api';

/**
 * @description:  常用的contentTyp类型
 */
export const ContentType = {
  TEXT: { 'Content-Type': 'text/plain' },
  JSON: { 'Content-Type': 'application/json; charset=utf-8' },
  FORM_URLENCODED: { 'Content-Type': 'application/x-www-form-urlencoded' },
  MULTIPART: { 'Content-Type': 'multipart/form-data' },
  OCTET_STREAM: { 'Content-Type': 'application/octet-stream' },
} as const;

/** 所有可能的响应 */
export type AllProtocol = Protocol | PlacesSearchResult;

// 1. 创建实例（可按需加通用配置：baseURL、超时、拦截器等）
const http = axios.create({
  baseURL: '',
  withCredentials: true, // 允许跨域携带 cookie
  timeout: 10_000,
});

export function requestConfig(headers: Record<string, string>): AxiosRequestConfig {
  return { headers: { ...headers } };
}

http.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // let each request carry token
    // this example using the JWT token
    // Authorization is a custom headers key
    // please modify it according to the actual situation
    const token = getToken();
    if (token) {
      if (!config.headers) {
        config.headers = {};
      }
      config.headers['X-Authorization-Token'] = token;
    }
    return config;
  },
  (error) => {
    // do something
    return Promise.reject(error);
  }
);

/* 类型守卫 */
function isGoogle(res: AllProtocol): res is PlacesSearchResult {
  return Array.isArray((res as PlacesSearchResult).places);
}

function isEmptyObject(res: unknown) {
  // 必须是对象且不是 null
  if (res === null || typeof res !== 'object') {
    return false;
  }

  // 没有任何自身属性
  return Object.keys(res).length === 0;
}

// add response interceptors
http.interceptors.response.use(
  (response: AxiosResponse<AllProtocol>) => {
    const res = response.data;
    if (isEmptyObject(res) || isGoogle(res)) {
      return res;
    }

    /* 2. 默认业务协议 */
    if (res.returncode !== 0) {
      Message.error({ content: res.message || 'Error', duration: 5 * 1000 });
    }
    return res;
  },
  (error) => {
    Message.error({
      content: error.msg || 'Request Error',
      duration: 5 * 1000,
    });
    return Promise.reject(error);
  }
);

export const request = {
  get<V = any>(url: string, params?: Record<string, any>): Promise<V> {
    return http.get(url, {
      params,
      paramsSerializer: (obj) => {
        return qs.stringify(obj);
      },
    });
  },

  post<V = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<V> {
    return http.post(url, data, config);
  },

  /**
   * POST application/x-www-form-urlencoded
   * @param url 请求地址
   * @param data 普通对象，如 {a:1,b:2}
   */
  form<T = any>(url: string, params?: Record<string, any>): Promise<T> {
    return http.post(url, qs.stringify(params), {
      headers: ContentType.FORM_URLENCODED,
    });
  },

  /**
   * POST application/json
   * @param url 请求地址
   * @param data 普通对象，如 {a:1,b:2}
   */
  json<T = any>(url: string, data?: any): Promise<T> {
    return http.post(url, data, { headers: ContentType.JSON });
  },

  /**
   * POST multipart/form-data
   * @param url 请求地址
   * @param formData FormData 对象
   */
  multipart<T = any>(url: string, formData: FormData): Promise<T> {
    // FormData 会自动生成 boundary 并添加到 Content-Type 中
    return http.post(url, formData);
  },
};
